#ifndef SP_FS_EXT2_H
#define SP_FS_EXT2_H

#include <fs/vfs.h>

// Flags
#define EXT2_FLG_CLEAN				0x0001 	 // File system is clean
#define EXT2_FLG_ERROR				0x0002 	 //File system has errors
#define EXT2_FLG_ORPHAN_RECOVERING	0x0004 	 //Orphan inodes are being recovered

// Error FLags
#define EXT2_ER_CONTINUE 	1
#define EXT2_ER_RO_MOUNT 	2 //	Remount file system as read only
#define EXT2_ER_PANIC		3 

// Creator OS Flags
#define EXT2_OS_LINUX	0
#define EXT2_OS_HURD	1
#define EXT2_OS_MASIX	2
#define EXT2_OS_FREEBSD	3
#define EXT2_OS_LITES	4

/*
Compatible Features Flags
Flag Value 	Description
0x0001 	Preallocate directory blocks to reduce fragmentation
0x0002 	AFS server inodes exist
0x0004 	File system has a journal (Ext3)
0x0008 	Inodes have extended attributes
0x0010 	File system can resize itself for larger partitions
0x0020 	Directories use hash index
Incompatible Features Flags
Flag Value 	Description
0x0001 	Compression
0x0002 	Directory entries contain a file type field
0x0004 	File system needs recovery
0x0008 	File system uses a journal device
Read Only Compatible Features Flags
Flag Value 	Description
0x0001 	Sparse superblocks and group descriptor tables
0x0002 	File system contains a large file
0x0004 	Directories use B-Trees 

  Filemode flags
Bits 0-8 Permission Flag 	In Octal 	Description
0x001 	0001 	Other—execute permission
0x002 	0002 	Other—write permission
0x004 	0004 	Other—read permission
0x008 	0010 	Group—execute permission
0x010 	0020 	Group—write permission
0x020 	0040 	Group—read permission
0x040 	0100 	User—execute permission
0x080 	0200 	User—write permission
0x100 	0400 	User—read permission
Bits 9-11 Flag Value 	In Octal 	Description
0x200 	01000 	Sticky bit
0x400 	02000 	Set group ID
0x800 	04000 	Set user ID
*/

//Bits 12-15
#define EXT2_TP_FIFO		0x1000 	//FIFO
#define EXT2_TP_CHAR_DEV 	0x2000 	//Character device
#define EXT2_TP_DIR			0x4000 	//Directory
#define EXT2_TP_BLK_DEV		0x6000 	//Block device
#define EXT2_TP_REG_FILE	0x8000 	//Regular file
#define EXT2_TP_LINK		0xA000 	//Symbolic link
#define EXT2_TP_UNIX_SOCK	0xC000 	//Unix socket

/*
Inode flags
Flag Value 	Description
0x00000001 	Secure deletion (not used)
0x00000002 	Keep a copy of data when deleted (not used)
0x00000004 	File compression (not used)
0x00000008 	Synchronous updates—new data is written immediately to disk
0x00000010 	Immutable file (content cannot be changed)
0x00000020 	Append only
0x00000040 	File is not included in 'dump' command
0x00000080 	A-time is not updated
0x00001000 	Hash indexed directory
0x00002000 	File data is journaled with Ext3 

*/
// Filetypes
#define EXT2_FT_UNKNOWN 	0
#define EXT2_FT_REG_FILE 	1
#define EXT2_FT_DIR 		2
#define EXT2_FT_CHRDEV 		3
#define EXT2_FT_BLKDEV 		4
#define EXT2_FT_FIFO 		5
#define EXT2_FT_SOCK 		6
#define EXT2_FT_SYMLINK 	7
#define EXT2_FT_MAX 		8 

#include <klibc/ctype.h>
#include <system/mod.h>

/*
 * Superblock
 */
typedef struct
{
	uint32_t inodes_num; 				//0–3 	 Number of inodes in file system
	uint32_t blocks_num; 				//4–7 	Number of blocks in file system
	uint32_t blocks_reserved_num; 		//8–11 	Number of blocks reserved to prevent file system from filling up
	uint32_t blocks_unallocated; 		//12–15 	Number of unallocated blocks
	uint32_t inodes_unallocated;		//16–19 	Number of unallocated inodes
	uint32_t block_group0_start; 		//20–23 	Block where block group 0 starts
	uint32_t block_size;				//24–27 	Block size (saved as the number of places to shift 1,024 to the left)
	uint32_t fragment_size; 			//28–31 	Fragment size (saved as the number of bits to shift 1,024 to the left)
	uint32_t blocks_of_group; 			//32–35 	Number of blocks in each block group
	uint32_t fragments_of_group; 		//36–39 	Number of fragments in each block group
	uint32_t inodes_of_group; 			//40–43 	Number of inodes in each block group
	uint32_t last_mount_time; 			//44–47 	Last mount time
	uint32_t last_writtend_time; 		//48–51 	Last written time
	uint8_t mount_count; 				//52–53 	Current mount count
	uint8_t mount_count_max; 			//54–55 	Maximum mount count
	uint8_t signature; 					//56–57 	Signature (0xef53)
	uint8_t fs_state; 					//58–59 	File system state (see below)
	uint8_t error_handling_method; 		//60–61 	Error handling method (see below)
	uint8_t minor_version; 				//62–63 	Minor version
	uint32_t last_check_time; 			//64–67 	Last consistency check time
	uint32_t check_interval; 			//68–71 	Interval between forced consistency checks
	uint32_t creator_os; 				//72–75 	Creator OS (see below)
	uint32_t major_version; 			//76–79 	Major version (see below)
	uint8_t uid_2reserved; 				//80–81 	UID that can use reserved blocks
	uint8_t gid_2reserved; 				//82–83 	GID that can use reserved blocks
	uint32_t first_non_reserver_inode; 	//84–87 	First non-reserved inode in file system
	uint8_t inode_size; 				//88–89 	Size of each inode structure
	uint8_t superblock_group; 			//90–91 	Block group that this superblock is part of (if backup copy)
	uint32_t feature_flags; 			//92–95 	Compatible feature flags (see below)
	uint32_t feature_incompatible; 		//96–99 	Incompatible feature flags (see Table below)
	uint32_t feature_read_only; 		//100–103 	Read only feature flags (see Table below)
	uint32_t fs_id; 					//104–119 	File system ID
	char volume_name[16];				//120–135 	Volume name
	char last_mount_path[64]; 			//136–199 	Path where last mounted on
	uint32_t bitmap_algorithm; 			//200–203 	Algorithm usage bitmap
	uint8_t blocks_2_prealloc_4_file;	//204–204 	Number of blocks to preallocate for files
	uint8_t blocks_2_prealloc_4_dir;	//205–205 	Number of blocks to preallocate for directories
	uint8_t unused1; 					//206–207 	Unused
	char journaled_id[16]; 				//208–223 	Journal ID
	uint32_t journaled_inode; 			//224–227 	Journal inode
	uint32_t journaled_device; 			//228–231 	Journal device
	uint32_t orphan_inodes_list;		//232–235 	Head of orphan inode list
	uint8_t unused2[788]; 				//236–1023 	Unused 
} ext2_superblock_t;





// Group Descriptor Table
typedef struct
{
	uint32_t starting_block_block_bm; //0–3 	Starting block address of block bitmap
	uint32_t starting_block_inode_bm; //4–7 	Starting block address of inode bitmap
	uint32_t starting_block_inode_tl; //8–11 	Starting block address of inode table
	uint8_t unalloc_block_in_group; //12–13 	Number of unallocated blocks in group
	uint8_t unalloc_inodes_in_group; //14–15 	Number of unallocated inodes in group
	uint8_t dir_in_group;				//16–17 	Number of directories in group
	uint8_t unused[14]; //18–31 	Unused
} ext2_group_table_t;

/*
Inode
Byte Range 	Description
0–1 	File mode (type and permissions)
2–3 	Lower 16 bits of user ID
4–7 	Lower 32 bits of size in bytes
8–11 	Access Time
12–15 	Change Time
16–19 	Modification time
20–23 	Deletion time
24–25 	Lower 16 bits of group ID
26–27 	Link count
28–31 	Sector count
32–35 	Flags
36–39 	Unused
40–87 	12 direct block pointers
88–91 	1 single indirect block pointer
92–95 	1 double indirect block pointer
96–99 	1 triple indirect block pointer
100–103 	Generation number (NFS)
104–107 	Extended attribute block (File ACL)
108–111 	Upper 32 bits of size / Directory ACL Yes /
112–115 	Block address of fragment
116–116 	Fragment index in block
117–117 	Fragment size
118–119 	Unused
120–121 	Upper 16 bits of user ID
122–123 	Upper 16 bits of group ID
124–127 	Unused 
*/


// Directory info
#define EXT2_FNAME_DIM	255

typedef struct
{
	uint32_t inode;
	uint8_t record_lenght; //4-5 	Record Length (Will get you to the next record)
	uint8_t name_lenght; //6 	Name Length
	uint8_t file_type; //7 	File Type
	char file_name[EXT2_FNAME_DIM]; //8-X 	File name data 
} ext2_dir_info_t;


extern module_t ext2_module;

vfs_node_t *ext2fs_root;

uint32_t ext2_init();
uint32_t ext2_shut();

uint8_t ext2_readdir(vfs_node_t *, char *, uint32_t);
vfs_node_t *ext2_finddir(vfs_node_t *, char *);

#endif
